# Copyright (c) 2008, Luke Freeman
# All rights reserved.

# Redistribution and use in source and binary forms, with or without modification, 
# are permitted provided that the following conditions are met:
#
#    * Redistributions of source code must retain the above copyright notice, this 
#      list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above copyright notice, this 
#      list of conditions and the following disclaimer in the documentation and/or 
#      other materials provided with the distribution.
#    * Neither the name of Flag-Up nor the names of its contributors may 
#      be used to endorse or promote products derived from this software without specific 
#      prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
# POSSIBILITY OF SUCH DAMAGE.

import sys, os, re
import gconf
import gtk
from base.singleton import *


# globals
CONFIGURATION_ROOT = "/apps/flag-up"
configuration = gconf.client_get_default()


# dummy class for snap-in loading
class SnapIn(object):
	
	ROOT_DIR = "./snap_ins"
	
	description = "Contact the developer to fix this"
	author = "Developer Name"
	type = ""
	type_description = "#ERROR"


	def get_icon(type, width=16, height=16):
		file_name = os.path.join(SnapIn.ROOT_DIR + "/icons/", type + ".png")
		if (not os.path.isfile(file_name)):
			file_name = os.path.join(SnapIn.ROOT_DIR + "/icons/", "generic.png")
		pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(file_name, width, height)
		return pixbuf

	get_icon = staticmethod(get_icon)


# TODO thread safety
class Configuration(Singleton):
		
    first_time = None
			
    def __init__(self):

        # prevent loading after the first time
        if self.first_time == None:
            self.first_time = self.is_configured
            if self.first_time is None or self.first_time is False:
                self.do_initial_setup()
            else:
                self.load()


    def __full_conf_path(self, conf_item):
        return "%s%s" % (CONFIGURATION_ROOT, conf_item)	
	
		
    def load(self):
        snapin_path = self.get_value("/snap_in_dir")
        self.__init_snapin_system(snapin_path)
	

    def do_initial_setup(self):
        initial_config = {
            "/snap_in_dir": "%s/snap_ins" % os.getcwd(),
            "/is_configured": False,
            "/check_interval": 5,
            "/flash/do": True,
            "/flash/indef": True,
            "/flash/fixed": False,
            "/flash/fixed_interval": 5
        }

        for conf_key in initial_config.keys():
            self.set_value(conf_key, initial_config[conf_key])
        
        self.load()              # load the initial config



    # attribute accessors    def get_is_configured(self):
        is_configured = self.get_value("/is_configured")
        return True if is_configured else False

    def set_is_configured(self, is_configured):
        self.set_value("/is_configured", is_configured)
    
    is_configured = property(get_is_configured, set_is_configured)
    
    

    # configuration functions
    def set_value(self, key, value):
        full_key = self.__full_conf_path(key)
        configuration.set_value(full_key, value)    

    def get_value(self, key):
        full_key = self.__full_conf_path(key)
        try:
            value = configuration.get_value(full_key)  
            return value
        except ValueError:
            return None
    
    
    # snap-ins
    # snap-in configuration / initialization
    def __load_snapins(self, directory):
        files = os.listdir(directory)
        regex = re.compile('^(?!__)\w+(.py)$')      # find all files ending in '.py' not starting with '__'
        for f in files:
            if regex.match(f):
                module = f.split(".")[0]
                __import__(module, None, None, [''])

    def __init_snapin_system(self, directory):
        if os.path.exists(directory):
            if not directory in sys.path:
                sys.path.insert(0, directory)
            self.__load_snapins(directory)        
        else:  # cannot initialise snap-ins: path does not exist
            raise "Cannot configure snap-ins: snap-ins path is invalid or does not exist"
    

    # snap in retrieval functions    
    
    def snapin_by_type_description(self, type_desc):
        snapins = self.all_snapins()
        for snapin in snapins:
            if snapin.type_description == type_desc:
                return snapin
    
        return None
    
    
    # return all snap-ins
    def all_snapins(self):
        return SnapIn.__subclasses__()
    
    
